﻿
namespace TaxCalculationChallenge
{
    /// <summary>
    /// Performs tax calculation.
    /// </summary>
    public class TaxCalculator
    {
        private readonly decimal[] maxTaxValues;
        private readonly int[] percentages;
        private decimal[] precalculatedTaxes;

        private TaxCalculator(decimal[] maxTaxValues, int[] percentages)
        {
            this.maxTaxValues = maxTaxValues;
            this.percentages = percentages;

            PrecalculateTaxes(maxTaxValues, percentages);
        }

        /// <summary>
        /// Create an Israel Tax Calculator.
        /// </summary>
        public static TaxCalculator CreateIsraelTaxCalculator()
        {
            return new TaxCalculator(
                new[] { 0m, 5070m, 8660m, 14070m, 21240m, 40230m },
                new[] { 10, 14, 23, 30, 33, 45 });
        }

        /// <summary>
        /// Calculate the tax from a specific amount of money.
        /// </summary>
        /// <param name="amount">The amount of money.</param>
        /// <returns>The tax to pay.</returns>
        public decimal Calculate(decimal amount)
        {
            int i = GetTaxRatePosition(amount);

            return precalculatedTaxes[i] + (amount - maxTaxValues[i]) * percentages[i] / 100m;
        }

        private void PrecalculateTaxes(decimal[] maxTaxValues, int[] percentages)
        {
            precalculatedTaxes = new decimal[maxTaxValues.Length];
            precalculatedTaxes[0] = 0;

            for (int i = 1; i < maxTaxValues.Length; ++i)
            {
                precalculatedTaxes[i] = precalculatedTaxes[i - 1] +
                                        (maxTaxValues[i] - maxTaxValues[i - 1]) * percentages[i - 1] / 100m;
            }
        }

        private int GetTaxRatePosition(decimal amount)
        {
            for (int i = 1; i < maxTaxValues.Length; i++)
            {
                if (amount < maxTaxValues[i]) return (i - 1);
            }

            return maxTaxValues.Length - 1;
        }
    }
}
